#region Copyright RenGuiYou. All rights reserved.
//=====================================================
// PandoraFrameWork
// Author:      RenGuiyou
// Feedback: 	mailto:750539605@qq.com
//=====================================================
#endregion
using System;
using System.Collections.Generic;
using System.Reflection;

namespace Pandora
{
	public struct AbbrStruct<T> where T: Attribute
	{
		public readonly T attribute;
		public readonly MethodInfo methodInfo;
		public readonly Type type;
		public AbbrStruct(Type type)
		{
			this.type = type;
			attribute = null;
			methodInfo = null;
		}
		public AbbrStruct(T t, Type type)
		{
			attribute = t;
			this.type = type;
			methodInfo = null;
		}
		public AbbrStruct(T t, MethodInfo methodInfo)
		{
			attribute = t;
			this.methodInfo = methodInfo;
			type = null;
		}
	}
	public static class PdrAssemblyHelper
	{
		public static Assembly[] GetAssemblies()
		{
			return AppDomain.CurrentDomain.GetAssemblies();
		}

		public static Type[] GetTypesFromAssembly(Assembly assembly)
		{
			if (assembly == null)
			{
				return Type.EmptyTypes;
			}
			Type[] result;
			try
			{
				result = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException)
			{
				result = Type.EmptyTypes;
			}
			return result;
		}

		public static List<AbbrStruct<T>> GetAttributeClass<T>() where T : Attribute
		{
			var list = new List<AbbrStruct<T>>();
			Assembly[] loadedAssemblies = GetAssemblies();
			foreach (var assembly in loadedAssemblies)
			{
				Type[] typesFromAssembly = GetTypesFromAssembly(assembly);
				foreach (var type in typesFromAssembly)
				{
					object[] customAttributes = type.GetCustomAttributes(typeof(T), false);
					if (customAttributes.Length!=0)
					{
						list.Add(new AbbrStruct<T>(customAttributes[0] as T,type));
					}
				}
			}
			return list;
		}

		public static List<AbbrStruct<T>> GetAttributeMethod<T>() where T: Attribute
		{
			var list = new List<AbbrStruct<T>>();
			Assembly[] loadedAssemblies = GetAssemblies();
			foreach (var assembly in loadedAssemblies)
			{
				Type[] typesFromAssembly = GetTypesFromAssembly(assembly);
				foreach (var type in typesFromAssembly)
				{
					MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					foreach (var methodInfo in methods)
					{
						if (Attribute.GetCustomAttribute(methodInfo, typeof(T)) is T t)
						{
							list.Add(new AbbrStruct<T>(t, methodInfo));
						}
					}
				}
			}
			return list;
		}
	}
}
